# -*- coding: utf-8 -*-
from common import trace


class IntField:
    """
    数据描述符
    """

    @trace
    def __get__(self, instance, owner):
        return self.value

    def __set__(self, instance, value):
        if not isinstance(value, int):
            raise ValueError('must be int')
        if value < 0:
            raise ValueError('must be >= 0')
        self.value = value

    def __delete__(self, instance):
        raise AttributeError("can't delete attribute")


class NonDataIntField:
    """非数据描述符"""

    def __get__(self):
        pass


class User:
    age = IntField()
    """
    属性查找顺序
    如果user是类的实例，user.age（等价于getattr(user,'age'))
    1. 首先调用__getattribute__, 如果类定义了 __getattr__方法，那么当__getattribute__抛出AttributeError的时候，就会调用 __getattr__
    2. 对于描述符(__get__)的调用，则是发生在__getattribute__内部的，　
    user = User(), 那么user.age顺序如下:
      2.1 如果"age"是出现在User或其基类的__dict__中，且　age是data descriptor, 那么调用其__get__方法
      2.2 如果 "age" 出现在 obj的 __dict__中，　那么直接返回 obj.__dict__['age']
      2.3 如果 "age"出现在User或其基类的__dict__中：
        2.3.1 如果age 是non-data descriptor, 那么调用其 __get__方法
        2.3.2 返回 __dict__['age']
    3. 如果User有__getattr__方法，调用__getattr__方法
    4. 抛出AttributeError
    
    
    """
    def __init__(self):
        # self.age = 10
        pass


if __name__ == '__main__':
    user = User()
    user.__dict__['age'] = 12
    # user.age = 12
    print(user.__dict__)
    print('user.age: {}'.format(user.age))
    print(User.age)

